﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

//因为"服务"是个标准端口模块,所以不能直接启动,要通过这个host宿主对象.
//形象的理解就是"服务"是个dll,这个是exe,组合起来才能用

//需要引用"服务"程序集
//host 属性页-从 "启动对象" 列表中选择 "服务"。
//GettingStarted 属性页-WCF选项-取消选中 "在调试同一解决方案中的另一个项目时启动 WCF 服务主机"。

namespace JoinBoxHost
{

    public class Host<TInterface, TClass> : IDisposable
    {
        private ServiceHost _myHelloHost; // 定义一个服务对象

        //public const string BaseAddress = "net.pipe://localhost"; //基地址,这样的报错的

        static Type _ContractType = typeof(TInterface);     //服务契约(暴露函数)接口
        static Type _ServiceType = typeof(TClass);          //服务契约(暴露函数)实现类型
        string _ServiceAddress = _ServiceType.Name;         //可选地址
        public string BaseAddress { get; set; }             //基地址(约定进入的地址)  "http://localhost:8000/JoinBox/";
        public static Binding ServiceBinding { get; set; }  //服务定义一个绑定

        /// <summary>
        /// 构造方法
        /// </summary>
        public Host()
        {

        }

        /// <summary>
        /// 构造服务对象
        /// </summary>
        public void Build()
        {
            if (BaseAddress == null)
            {
                throw new ArgumentNullException("参数为空", nameof(BaseAddress));
            }
            if (ServiceBinding == null)
            {
                ServiceBinding = new WSHttpBinding();
            }

            try
            {
                _myHelloHost = new ServiceHost(_ServiceType, new Uri[] { new Uri(BaseAddress) });      //创建服务对象
                _myHelloHost.AddServiceEndpoint(_ContractType, ServiceBinding, _ServiceAddress);       //添加终结点

                // Step 4: 启用元数据交换。
                var smb = new ServiceMetadataBehavior
                {
                    HttpGetEnabled = true
                };
                _myHelloHost.Description.Behaviors.Add(smb);
            }
            catch (CommunicationException ce)
            {
                _myHelloHost.Abort();
                throw ce;
            }
        }

        /// <summary>
        /// 打开服务方法
        /// </summary>
        public void Start()
        {
            try
            {
                Console.WriteLine("开始启动服务...");
                _myHelloHost.Opened += HostStart;
                _myHelloHost.Open();
            }
            catch (CommunicationException ce)
            {
                _myHelloHost.Abort();
                throw ce;
            }
        }

        private void HostStart(object sender, EventArgs e)
        {
            Console.WriteLine("Host已启动");
        }

        /// <summary>
        /// 销毁服务宿主对象实例
        /// </summary>
        public void Dispose()
        {
            if (_myHelloHost != null)
            {
                _myHelloHost.Close();
                (_myHelloHost as IDisposable).Dispose();
                _myHelloHost = null;
            }
        }
    }
}
